from server import app, api_auth, db, user_opt
from server.model.sys.sys_user import SysUser
from server.model.sys.route import Route
from datetime import datetime
from server.model.sys import PERMISSION
from sqlalchemy import and_
from flask import g, request, jsonify, Blueprint
from server.model import set_field, query_by_field
import math

sys_user = Blueprint('sys_user', __name__)


@api_auth.verify_token
def verify_token(token):
    if not token:
        return False

    user = SysUser.verify_auth_token(token)
    if not user:
        return False
    g.user = user
    return True


@api_auth.error_handler
def unauthorized():
    return jsonify({
        'code': 401,
        'message': "Unauthorized access"
    })


@sys_user.route('/login', methods=['POST'])
def login():
    """
            @@@
            #### Args:
                    {
                        username: String(64)    #用户名
                        password: String(255)    #密码
                        gate_id
                    }
            #### Returns::
                    {'code': 20000, 'message': "登录成功"}
                    {'code': 50001, 'message': "未知错误"}
            """
    args = request.get_json()
    username = args.get('username')
    psw = args.get('password')
    try:
        user = SysUser.query.filter(SysUser.username == username).first()
        if user is None or not user.check_psw(psw):
            return jsonify({
                'code': 50001,
                'message': "用户名或密码错误"
            })

        from server.model.sys.sys_login_record import SysLoginRecord
        record = SysLoginRecord(user_id=user.id, login_time=datetime.now(), username=user.username,
                                name=user.name, ip=request.remote_addr)

        db.session.add(record)
        db.session.commit()
        g.user = user
        g.user.user_type = 'sys'
        token = user.generate_auth_token()
        print("the token", token.decode())
        return jsonify({
            'code': 20000,
            "token": "JWT %s" % token.decode()
        })
    except Exception as e:
        print("login error", e)
        return jsonify({
            'code': 50001,
            'message': "未知错误"
        })


@sys_user.route('/logout', methods=['POST'])
@api_auth.login_required
def logout():
    g.user = None
    return jsonify({
        'code': 20000,
        "message": "logout success"
    })


@sys_user.route('/info', methods=['GET'])
@api_auth.login_required
def admin_info():
    """
                @@@
                #### Args:

                #### Returns::
                        'code': 20000,
                         'data': {
                             'avatar': 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
                             'introduction': "I am a super administrator",
                             'name': 'Super Admin',
                             'is_agent': False,
                             "routes": [route.to_dict_with_permission(route_permissions) for route in top_routes if route.to_dict_with_permission(route_permissions)],
                             'roles': [role.to_dict() for role in user.ROLES]
                         }
                """
    user = g.user

    roles = user.get_roles()
    role_routes = []
    try:
        for role in roles:
            role_routes += role.get_role_routes()

        route_permissions = {}
        for role_route in role_routes:
            route_id = role_route.route_id
            permission = role_route.permission
            if route_id in route_permissions:
                route_permissions[route_id] |= permission
            else:
                route_permissions[route_id] = permission

        for key, value in route_permissions.items():
            route_permissions[key] = PERMISSION.crud(value)

        top_routes = Route.query.filter(and_(Route.id.in_(route_permissions), Route.parent_id == "0")).all()
        print("--admin info---", roles)
        return jsonify({
            'code': 20000,
            'data': {
                'avatar': 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
                'introduction': "I am a super administrator",
                'name': 'Super Admin',
                "routes": [route.to_dict_with_permission(route_permissions) for route in top_routes if
                           route.to_dict_with_permission(route_permissions)],
                'roles': [role.to_dict() for role in user.get_roles()],
                "user": user.to_dict(exclude={"password"})
            }
        })
    except Exception as e:
        print("get admin info error:", e)
    return jsonify({
        'code': 50001,
        'message': "未知错误"
    })


# 获取管理员列表
@sys_user.route('', methods=['GET'])
@api_auth.login_required
def get_admins():
    """
            @@@
            #### Args:

            #### Returns::
                    {
                        "code": 20000,
                        "items": [
                          {
                          ]
                    }
            """
    page = request.args.get('page', type=int, default=1)
    limit = request.args.get('limit', type=int, default=20)
    query_filter = request.args.get('filter')
    try:
        users = SysUser.query
        users = query_by_field(users, query_filter, SysUser)
        total = users.count()
        users = users.offset((page - 1) * limit).limit(limit).all()

        return jsonify({
            'code': 20000,
            'items': [user.to_dict(exclude={'password'}) for user in users],
            'totalCount': total,
            'TotalPageCount': math.ceil(int(total / limit))
        })
    except Exception as e:
        print("get admins error", e)

    return jsonify({
        'code': 50001,
        'message': "未知错误"
    })


@sys_user.route('/<int:pid>', methods=['PUT'])
@api_auth.login_required
def edit_admin(pid):
    """
        @@@
        #### Args:
                {
                    roles
                    password
                }
        #### Returns::
                {'code': 20000, 'message': "修改成功"}
                {'code': 50001, 'message': "未知错误"}
        """
    args = request.get_json()
    role_ids = args.get('roles')
    password = args.get('password')
    try:
        user = SysUser.query.filter_by(id=pid).one_or_none()

        args['updater'] = g.user.name
        args.pop('roles')
        if password:
            args.pop('password')
            user.set_psw(password)
        set_field(user, args)

        from server.model.sys.sys_user_role import SysUserRole
        SysUserRole.query.filter_by(user_id=user.id).delete()

        for role_id in role_ids:
            db.session.add(SysUserRole(user_id=user.id, role_id=role_id))

        db.session.commit()

        user_opt.send({
            "operation": "修改管理员",
            "method": "系统管理",
            "params": pid,
            "user_id": g.user.id,
            "username": g.user.username
        })

        return jsonify({'code': 20000, 'message': "修改成功"})
    except Exception as e:
        print(e)
        return jsonify({
            'code': 50001,
            'message': "未知错误"
        })


@sys_user.route('', methods=['POST'])
@api_auth.login_required
def add_admin():
    """
        @@@
        #### Args:
                {
                   username = Column(String(64), nullable=False, server_default='', comment="用户名 ")
                   password = Column(String(255), nullable=False, server_default='', comment="密码 ")
                   nickname = Column(String(64), nullable=False, server_default='', comment="姓名(昵称) ")
                   mobile = Column(String(32), nullable=False, server_default='', comment="手机号 ")
                   status = Column(TINYINT(4), nullable=False, server_default='0', comment="状态 0:禁用，1:正常 ")
                   remark = Column(String(64), nullable=False, server_default='', comment="备注 ")
                   is_modify_pwd = Column(TINYINT(4), nullable=False, server_default='0', comment="是否修改过初始密码 ")
                }
        #### Returns::
                {'code': 20000, 'message': "添加成功"}
                {'code': 50001, 'message': "未知错误"}
        """

    args = request.get_json()

    username = args.get('username')
    password = args.get('password')
    role_ids = args.get('roles')
    print("adding admin:", args)

    try:
        user = SysUser.query.filter_by(username=username).one_or_none()
        if user:
            return jsonify({
                'code': 50001,
                'message': 'username repeated!'
            })
        user = SysUser(username=username)

        args['creator'] = g.user.name

        db.session.add(user)
        args.pop('roles')
        args.pop('password')
        set_field(user, args)
        user.set_psw(password)
        db.session.flush()

        for role_id in role_ids:
            from server.model.sys.sys_user_role import SysUserRole
            db.session.add(SysUserRole(user_id=user.id, role_id=role_id))

        db.session.commit()

        user_opt.send({
            "operation": "系统管理",
            "method": "添加管理员",
            "params": user.id,
            "user_id": g.user.id,
            "username": g.user.username
        })
        return jsonify({'code': 20000, 'message': "添加成功"})
    except Exception as e:
        print("add_admin error:", e)

    return jsonify({'code': 50001, 'message': "未知错误"})


@sys_user.route('/<int:pid>', methods=['DELETE'])
@api_auth.login_required
def remove_admin(pid):
    """
        @@@
        #### Args:
                {
                   "ID": 1,
                }
        #### Returns::
                {'code': 20000, 'message': "删除成功"}
                {'code': 50001, 'message': "未知错误"}
        """
    try:

        user = SysUser.query.filter_by(id=pid).one_or_none()
        user_id = user.id
        # 删除关联roles将被动删除
        db.session.delete(user)
        from server.model.sys.sys_user_role import SysUserRole
        SysUserRole.query.filter_by(user_id=user.id).delete()
        db.session.commit()

        user_opt.send({
            "operation": "系统管理",
            "method": "删除管理员",
            "params": user_id,
            "user_id": g.user.id,
            "username": g.user.username
        })
        return jsonify({'code': 20000, 'message': "删除成功"})
    except Exception as e:
        print(e)
        return jsonify({
            'code': 50001,
            'message': "未知错误"
        })
